import json
import numpy as np
import pandas as pd
from file_info import FileInfo


def is_number(data):
    # 判断数据是不是数字
    try:
        float(data)
        return True
    except ValueError:
        return False


class DiffColsError(BaseException):
    def __init__(self, first_col_num, other_col_num, idx):
        self.msg = "文件不同行的列数不一致。文件的第1行的列数为：{}，第{}行的列数为：{}".format(first_col_num, idx+1, other_col_num)


class OpenFile(object):
    """
    * 打开文件类
    * 只需要调用openfile()方法即可根据文件类型打开txt,csv,xlsx,dat等数据文件
    * 返回: 会返回FileInfo类型数据
    * 打开数据需要能够放置于table表格中，故数据应较为规整，若无法打开数据，会提示行列数不一致
    """
    def __init__(self):
        pass

    def read_txt(self, file_path):
        try:
            file_info = self.open_text(file_path)
            file_info.type = ".txt"
            return file_info
        except:
            print("文件格式错误，无法打开！")

    def read_csv(self, file_path):
        try:
            df = pd.read_csv(file_path)
            file_info = self.get_file_info(file_path, df)
            file_info.type = ".csv"
            return file_info
        except:
            print("文件格式错误，无法打开！")

    def read_dat(self, file_path):
        file_info = self.open_text(file_path)
        file_info.type = ".dat"
        return file_info

    def read_excel(self, file_path):
        try:
            df = pd.read_excel(file_path, sheet_name='Sheet1')
            file_info = self.get_file_info(file_path, df)
            file_info.type = ".xlsx"
            return file_info
        except:
            print("文件格式错误，无法打开！")

    def read_json(self, file_path):
        try:
            with open(file_path, 'r', encoding='utf=8') as file:
                data = json.load(file)
                return data
        except:
            print("文件格式错误，无法打开！")

    def get_file_info(self, file_path, df):
        # 打开csv,xlsx类型文件
        file_info = FileInfo()
        file_name = file_path.split('/')[-1]
        name = file_name.split(".")[0]
        file_info.name = name

        file_cols = len(df.keys())
        file_rows = len(df[df.keys()[0]])
        file_info.cols_count = file_cols
        for i in df.keys():
            if not is_number(i):
                file_info.have_head = True
        if file_info.have_head:
            file_info.rows_count = file_rows
            file_info.head_label = df.keys().tolist()
            file_info.data = df.to_numpy()
        else:
            file_info.head_label = [str(i+1) for i in range(file_cols)]
            file_info.rows_count = file_rows + 1
            first_row = df.keys().to_list()
            data = df.to_numpy()
            data = np.insert(data, 0, first_row, axis=0)
            file_info.data = data
        file_info.have_head = True
        return file_info

    def get_filename(self, file_path):
        # 根据文件路径获取文件名
        file = file_path.split('/')[-1]
        filename = file.split('.')[0]
        return filename

    def have_head(self, line):
        # 判断文件是否有第一行的表头
        for word in line.strip().split():
            word = word.strip()
            if not is_number(word):
                return True
        return False

    def str_to_float(self, line):
        # 把字符类型转成float类型
        data_line = []
        for word in line.strip().split():
            word = word.strip()
            word = float(word)
            if word != "":
                data_line.append(word)
        return data_line

    def open_text(self, file_path):
        """ 打开txt,dat类型的文件 """
        file_info = FileInfo()
        file_info.name = self.get_filename(file_path)
        z_data = []
        with open(file_path, "r") as fr:
            lines = fr.readlines()
            for idx, line in enumerate(lines):
                if idx == 0:
                    if "=" in line:
                        line = line.split("=")[1]
                    have_head = self.have_head(line)
                    len_col = len(line.strip().split())
                    file_info.cols_count = len_col
                    if have_head:
                        file_info.head_label = line.strip().split()
                        file_info.rows_count = len(lines) - 1
                    else:
                        file_info.head_label = [str(i+1) for i in range(len_col)]
                        file_info.rows_count = len(lines)
                        data_line = self.str_to_float(line)
                        z_data.append(data_line)
                    file_info.have_head = True
                else:
                    len_col = len(line.strip().split())
                    if len_col != file_info.cols_count:
                        raise DiffColsError(file_info.cols_count, len_col, idx)
                    data_line = self.str_to_float(line)
                    z_data.append(data_line)
        file_info.data = np.array(z_data)
        return file_info

    def openfile(self, file_path):
        # 根据文件后缀名打开不同类型文件
        extension_name = file_path.split(".")[-1]
        if extension_name == "txt" or extension_name == "TXT":
            file_info = self.read_txt(file_path)
        elif extension_name == "csv":
            file_info = self.read_csv(file_path)
        elif extension_name == "xlsx":
            file_info = self.read_excel(file_path)
        elif extension_name == "dat" or extension_name == "DAT":
            file_info = self.read_dat(file_path)
        elif extension_name == "json":
            file_info = self.read_json(file_path)
        else:
            file_info = FileInfo()
        return file_info

